import Feature from "ol/Feature";
import Point from "ol/geom/Point";
import Circle from "ol/geom/Circle"; // eslint-disable-line
import Icon from "ol/style/Icon";
import { Cluster, Vector as VectorSource } from "ol/source.js";
import { Circle as CircleStyle, Fill, Stroke, Style, Text } from "ol/style.js";
import Overlay from "ol/Overlay";
import { Select } from "ol/interaction";
import Polygon from "ol/geom/Polygon";
import MultiPolygon from "ol/geom/MultiPolygon";


function Marker(map) {
    this.map = map;
}

/**
 * description 捕获点击地图的要素
 * @param iconLayer 容纳要素的图层
 */
Marker.prototype.selectFeature = function(iconLayer, vm) {
    let selet = new Select({ layers: [iconLayer] });
    this.map.addInteraction(selet);
    selet.on("select", (e) => {
        if (e.selected.length == 0) return;
        // console.log("target", e.target.getFeatures())
        let feature = e.selected[0];
        //要素属性信息
        let attr = feature.getProperties();
        console.log("feature", attr);
        attr.coord = attr.geometry.getCoordinates();
        // console.log("选中了要素,coord=", attr.coordinate)
        vm.attr = attr;
        //使用该方法时，选中后有默认的选中图标，若不需要选中图标加上下面这行代码即可
        selet.getFeatures().clear();
    });
};

Marker.prototype.getDistrictInfo = function(vm) {
    //点击图标显示自定义弹出框
    this.map.on("click", function(e) {
        let pixel = this.getEventPixel(e.originalEvent);
        // console.log("pixel", pixel)
        this.forEachFeatureAtPixel(pixel, function(feature) {
            if (
                feature.getGeometry() instanceof Polygon ||
                feature.getGeometry() instanceof MultiPolygon
            ) {
                let attr = feature.getProperties();
                console.log("attr", attr);
                attr.coord = e.coordinate;
                attr.pixel = pixel;
                vm.attr = attr;
            }
        });
    });
};
/**
 * 添加弹出框
 * @param container 弹出框的容器(html元素)
 * @param coordinate 弹出框的坐标
 */

Marker.prototype.addPop = function(container, coordinate, offset) {
    let overlay = new Overlay({
        //设置弹出框的容器
        element: container,
        positioning: "bottom-center",
        offset: offset || [0, -10],
        // stopEvent: true,
        //是否自动平移，即假如标记在屏幕边缘，弹出时自动平移地图使弹出框完全可见
        autoPan: true,
        autoPanAnimation: {
            duration: 10,
            // 当Popup超出地图边界时，为了Popup全部可见，地图移动的速度.
        },
    });
    overlay.setPosition(coordinate);
    this.map.getView().animate({
        center: [coordinate[0], Number(coordinate[1]) + 0.01],
        zoom: 14,
        rotate: 0,
        duration: 800,
    });
    this.map.addOverlay(overlay);
};
/**
 * description 使用forEachFeatureAtPixel选中要素
 * @param vm
 */
Marker.prototype.getFeatureInfo = function(vm) {
    //点击图标显示自定义弹出框
    this.map.on("click", function(e) {
        let pixel = this.getEventPixel(e.originalEvent);
        // console.log("pixel", pixel)
        this.forEachFeatureAtPixel(pixel, function(feature) {
            // if(feature.getGeometry() instanceof Point||feature.getGeometry() instanceof Polygon) {
            if (feature.getGeometry() instanceof Point) {
                let attr = feature.getProperties();
                // console.log("attr", attr)
                vm.attr = attr;
                // console.log(vm.attr);
                // console.log(vm);
            }
        });
    });
};
/**
 * description 地图添加图标
 * @param coord 图标点坐标，必须
 * @param attr 图标点属性信息，非必须
 * @returns {VectorLayer<VectorSourceType>}
 */
Marker.prototype.addIcon = function(coord = [], attr = {}, style, layer) {
    style = style || {
        opacity: 0.95,
        src: "",
        anchor: [0.5, 16],
        anchorXUnits: "fraction",
        anchorYUnits: "pixels",
        scale: 0.2,
    };

    let iconStyle = new Style({
        /*icon样式*/
        image: new Icon(style),
    });

    let feature = new Feature({
        geometry: new Point(coord),
    });
    feature.setStyle(iconStyle);
    //添加点的时候赋值属性
    if (attr) {
        attr.coord = coord;
        feature.setProperties(attr);
    }
    layer.getSource().addFeature(feature);
    return feature;
};

/**
 * @description: 添加marker点(单个)
 * @param {*} lon 经度,必传
 * @param {*} lat 纬度,必传
 * @param {*} layer 图层对象,必传
 * @param {*} styleObj 样式对象
 * @param {*} markerInfo marker的属性信息
 * @return {*}
 */
Marker.prototype.addMarker = function(lon, lat, layer, styleObj, markerInfo, type) {
    let markerLayer = layer;
    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Point([lon, lat]), //标注信息
        markerInfo: markerInfo || "",
    });
    feature.type = type;
    feature.setStyle(createMarkerStyle(styleObj));
    let source = markerLayer.getSource();
    source.addFeature(feature);
    return feature;
};
/**
 * @description: 添加文字标注
 * @param {*} lon
 * @param {*} lat
 * @param {*} layer
 * @param {*} styleObj
 * @return {*}
 */
Marker.prototype.addText = function(lonlat, layer, styleObj) {
    let pointLayer = layer;
    //实例化Vector要素，通过矢量图层添加到地图容器中
    let feature = new Feature({
        geometry: new Point(lonlat),
    });
    feature.setStyle(createTextStyle(styleObj));
    let source = pointLayer.getSource();
    source.addFeature(feature);
    return feature;
};


/**
 * @description: 添加marker点(多个),适用于一批相同样式的点，如果marker各不相同建议使用上面添加单个marker点的方法单独设置样式
 * @param {object} layer 图层对象,必传
 * @param {array} markerData 存放marker数据
 * @param {string} fieldName_lon 对应经度的字段名称
 * @param {string} fieldName_lat 对应纬度的字段名称
 * @param {object} styleObj 样式对象
 * @return {*}
 */
Marker.prototype.addMarkers = function(
    layer,
    markerData,
    fieldName_lon,
    fieldName_lat,
    styleObj
) {
    if (!markerData || markerData.length <= 0) return;

    let markerLayer = layer;
    let source = markerLayer.getSource();
    //实例化Vector要素，通过矢量图层添加到地图容器中
    let features = [];
    markerData.forEach((item) => {
        let feature = new Feature({
            geometry: new Point([item[fieldName_lon], item[fieldName_lat]]), //标注信息
            markerInfo: item || "",
        });
        feature.setStyle(createMarkerStyle(styleObj));
        features.push(feature);
    });
    //markerLayer.setStyle(createMarkerStyle(styleObj));
    source.addFeatures(features);
};

/**
 * @description: 添加gif动图格式的marker点（以overlay的element方式，解决openlayers无法加载gif图片等问题）
 * @param {array} _position 点的位置
 * @param {object} data marker属性信息
 * @param {object} _imgParam 图片的宽高及路径 如{width:'20px',height:'20px',src:''}
 * @param {string} _elementId overlay添加的容器Id
 * @param {string} _overlayId overlay的Id
 * @param {string} _className 样式类名
 * @param {function} _clickFunc 点击回调函数
 * @return {*}
 */
Marker.prototype.addMarkersByOverlay = function(
    _position,
    data,
    _imgParam,
    _elementId,
    _overlayId,
    _className,
    _clickFunc
) {
    let _overlay = document.getElementById(_elementId);
    if (document.getElementById(_overlayId)) {
        let _removeLyr = this.map.getOverlayById(_overlayId);
        this.map.removeOverlay(_removeLyr);
    }
    let sElement = document.createElement("div");
    sElement.id = _overlayId;
    sElement.style.width = _imgParam.width;
    sElement.style.height = _imgParam.height;
    sElement.style.backgroundImage = "url(" + _imgParam.src + ")";
    sElement.style.backgroundPosition = "center";
    sElement.style.backgroundRepeat = "no-repeat";
    sElement.style.backgroundSize = "contain";
    sElement.attr = data;
    sElement.className = _className;
    _overlay.appendChild(sElement);

    //新增overly
    let lyr = new Overlay({
        id: _overlayId,
        positioning: "bottom-center", //属性
        attributes: data, //overly放置的div
        element: sElement,
        stopEvent: false,
    });

    //逐个把overly添加到地图上
    this.map.addOverlay(lyr);
    lyr.setPosition(_position); //显示

    //如果点击事件
    if (_clickFunc) {
        sElement.onclick = function(evt) {
            if (!evt.currentTarget.attr) {
                return;
            }
            let attr = evt.currentTarget.attr;
            _clickFunc(attr, evt.currentTarget);
        };
    }
};

/**
 * @description: 添加聚合marker
 * @param {array} features marker要素点数组
 * @param {*} layer 图层对象
 * @param {*} styleObj 聚合后的样式
 *  {
 *    imgUrl:'', 图片路径
 *    fillColor:'', 文字颜色
 *    strokeColor:'', 文字边线颜色
 *    strokeWidth:'' 文字边线宽度
 *  }
 * @return {*}
 */
Marker.prototype.addClusterMarker = function(features, layer, styleObj) {
    //实例化Vector要素，通过矢量图层添加到地图容器中
    const source = new VectorSource({
        features: features,
    });

    const clusterSource = new Cluster({
        distance: 30,
        source: source,
    });
    const styleCache = {};
    layer.setSource(clusterSource);
    layer.setStyle(function(feature) {
        //let zoom = map.map.getView().getZoom();  //获取当前地图的缩放级别
        let size = feature.get("features").length;
        let style = styleCache[size];
        if (size == 1) {
            feature.get("features").forEach((value) => {
                // 通过value.get("属性名") 获取设置的值
                let markerInfo = value.get("markerInfo");
                style = new Style({
                    image: new Icon({
                        src: markerInfo.imgUrl,
                        rotation: markerInfo.rotate ? markerInfo.rotate : 0,
                    }),
                });
            });
        } else {
            style = new Style({
                image: new Icon({
                    src: styleObj.imgUrl,
                }),
                text: new Text({
                    text: size.toString(),
                    fill: new Fill({
                        color: styleObj.fillColor || "#333",
                    }),
                    stroke: new Stroke({
                        color: styleObj.strokeColor || "#333",
                        width: styleObj.strokeWidth || 1,
                    }),
                }),
            });
            styleCache[size] = style;
        }
        return style;
    });
};

/**
 * @description: marker点样式设置
 * @param {*} styleObj 样式对象，如果有图片路径，设置图片相关参数，如果没有图片，设置绘制点的样式
 * {
 *   imgUrl:图片路径
 *   imgOffsetX：图片x轴偏移量
 *   imgOffsetY：图片y轴偏移量
 *   rotate:图片旋转角度
 *   scale：图片缩放比
 *  ---------如果没有图片设置下面圆点marker的参数-----------
 *   radius：半径大小
 *   pBorderColor：边线的颜色
 *   pBorderWidth：边线的宽度
 *   pFillColor：填充颜色
 * }
 *
 * @return {*}
 */
function createMarkerStyle(styleObj) {
    let style = {};
    //图标
    if (styleObj.imgUrl) {
        let offsetX = styleObj.imgOffsetX || 0;
        let offsetY = styleObj.imgOffsetY || 0;
        style.image = new Icon({
            rotation: styleObj.rotate ? (styleObj.rotate * 3.1415926) / 180 : 0,
            scale: styleObj.scale || 1,
            src: styleObj.imgUrl,
            offset: [offsetX, offsetY],
        });
    } else {
        style.image = new CircleStyle({
            radius: styleObj.radius || 10,
            stroke: new Stroke({
                color: styleObj.pBorderColor || "#FFFFFF",
                width: styleObj.pBorderWidth || "2",
            }),
            fill: new Fill({
                color: styleObj.pFillColor || "#b8110b",
            }),
        });
    }
    if (styleObj.text) {
        // 设置marker的label
        style.text = new Text({
            text: styleObj.text.name,
            fill: new Fill({
                color: styleObj.text.fillColor || "#333",
            }),
            stroke: new Stroke({
                color: styleObj.text.strokeColor || "#333",
                width: styleObj.text.strokeWidth || 1,
            }),
            offsetY: styleObj.text.offsetY || 25,
            offsetX: styleObj.text.offsetX || 0,
            font: styleObj.text.font || "normal 14px 微软雅黑",
        });
    }
    return new Style(style);
}

//文字标注样式
function createTextStyle(styleObj) {
    let style = {};
    if (styleObj) {
        style.text = new Text({
            text: styleObj.name,
            textAlign: "center", // 位置
            font: styleObj.font || "bolder 10px 微软雅黑",
            fill: new Fill({
                color: styleObj.fillColor || "#333",
            }),
            // backgroundFill: new Fill({
            //     color: styleObj.backgroundFill || "#ffb663",
            // }),
            stroke: new Stroke({
                color: styleObj.strokeColor || "#333",
                width: styleObj.strokeWidth || 0.5,
            }),
            offsetX: styleObj.offsetX || 0,
            offsetY: styleObj.offsetY || 0,
        });
    }
    return new Style(style);
}

export default Marker;